﻿using System;
using System.Collections.Generic;
using System.Linq;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using FluentNHibernate.Mapping;
using NHibernate;
using NHibernate.Linq;

namespace NHCourse.Spikes
{
   internal class Program
   {
      private static void Main()
      {
         try
         {
            using (var sessionFactory = GetSessionFactory())
            using (var session = sessionFactory.OpenSession())
            {
               Console.WriteLine("Post count via 'Posts' property");
               Console.WriteLine();

               session.Linq<User>()
                  .Take(50)
                  .ToList()
                  .ForEach(x => Console.WriteLine("User: {0} - {1}, Posts: {2}", x.Id, x.DisplayName, x.Posts.Count));

               Console.WriteLine();
               Console.WriteLine();

               Console.WriteLine("Post count via custom query");
               Console.WriteLine();

               session.Linq<User>()
                  .Take(50)
                  .Select(user => new
                     {
                        user.Id,
                        user.DisplayName,
                        PostCount = user.Posts.Count
                     })
                  .ToList()
                  .ForEach(x => Console.WriteLine("User: {0} - {1}, Posts: {2}", x.Id, x.DisplayName, x.PostCount));
            }
         }
         catch (Exception ex)
         {
            Console.WriteLine(ex);
         }
      }

      private static ISessionFactory GetSessionFactory()
      {
         return Fluently
            .Configure()
            .Database(MsSqlConfiguration.MsSql2008.ConnectionString(@"Data Source=.\SQLEXPRESS;AttachDbFilename=C:\temp\NHCourse\NHCourse.Mvc\App_Data\StackOverflow.mdf;Integrated Security=True;User Instance=True").ShowSql())
            //.Database(SQLiteConfiguration.Standard.UsingFile(@"C:\temp\NHCourse\NHCourse.Mvc\App_Data\SO.sqlite").ShowSql())
            .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Program>())
            .BuildSessionFactory();
      }
   }

   public class User
   {
      public virtual int Id { get; protected set; }
      public virtual string DisplayName { get; protected set; }
      public virtual IList<Post> Posts { get; protected set; }
   }

   public class Post
   {
      public virtual int Id { get; protected set; }
      public virtual string Title { get; protected set; }
      public virtual User Owner { get; protected set; }
   }

   public class UserMap : ClassMap<User>
   {
      public UserMap()
      {
         Table("SO.Users");
         Id(m => m.Id);
         Map(m => m.DisplayName);
         HasMany(m => m.Posts).KeyColumn("OwnerUserId");
      }
   }

   public class PostMap : ClassMap<Post>
   {
      public PostMap()
      {
         Table("SO.Posts");
         Id(m => m.Id);
         Map(m => m.Title);
         References(m => m.Owner, "OwnerUserId");
      }
   }
}